#include "memory.h"
#include <fstream>
#include <sstream>
#include <cstring>
#include <cstdlib>
using namespace std;

Memory::Memory()
{
    memoryFile = "/proc/meminfo";

}

/*
Example:
MemTotal:        1996864 kB
MemFree:          902444 kB
Buffers:           58184 kB
Cached:           555616 kB
SwapCached:            0 kB

*/
void Memory::GetMemoryFromFile(MemoryFile *pFile)
{
    char memoryBuffer[100];
    FILE *fp = fopen(memoryFile,"r");
//    ifstream memoryStream(memoryFile);

    if(!fp){
        ErrorLog *pErr = new ErrorLog();
        pErr->log_error(AT,"无法打开文件：/proc/meminfo");
        exit(1);
    }
    else{
        char delims[] = ":";
        char de[] = " ";
        char *result = NULL;
        char cpy[100];

        fgets(memoryBuffer,100,fp);
        // 总的物理内存大小
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->memTotal = result;
        // 可用物理内存大小
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->memFree = result;
        // 内存使用率
        float pUse;
        pUse = (pFile->memTotal.toFloat() - pFile->memFree.toFloat()) / pFile->memTotal.toFloat();
        pFile->memUsedRate = QString("%1").arg(pUse);
        //缓冲区大小
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->buffers = result;
        // 用于高速缓存的大小
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->cached = result;
        // 用于高速缓存的交换分区大小
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->swapCached = result;
        // 活动内存量
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->active = result;
        // 不活动内存量
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->inActive = result;
        // 中间不需要
        for(int i = 0; i< 10; i++)
            fgets(memoryBuffer,100,fp);
        // 交换分区量
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->swapTotal = result;
        // 可用交换分区大小
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->swapFree = result;
        // 交换分区使用率
        float swapUse;
        swapUse = (pFile->swapTotal.toFloat() - pFile->swapFree.toFloat()) / pFile->swapTotal.toFloat();
        pFile->swapUsedRate = QString("%1").arg(swapUse);
        // 脏内存，可能要写到磁盘或者交换分区的内存
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->dirty = result;
         //
        for(int j = 0; j < 3; j++)
              fgets(memoryBuffer,100,fp);
        // 内核使用的内存量
        fgets(memoryBuffer,100,fp);
        result = strtok( memoryBuffer, delims );
        result = strtok(NULL, delims);
        strcpy(cpy,result);
        result =strtok(result,de);
        pFile->slab = result;
    }
}

//
void Memory::GetSwap(char *result, struct MemorySwap *pSwap)
{
    char *tmp = NULL;
//    char delim[] = "\n";
    char delims[] = " ";
//    char tmpcpy[200];
//
//    tmp = strtok(result,delim);
//
//    tmp = strtok(NULL,delim);
//
//    tmp = strtok(NULL,delim);

    // 此时的tmp 为“5  0      0 877560  92288 557300    0    0    70    57  307  943 13  4 81  2”
//    strcpy(tmpcpy,tmp);
    tmp = strtok(result,delims);
    for(int i = 0; i < 5 ; i++ )
        tmp =strtok(NULL,delims);
    // swap in
    tmp =strtok(NULL,delims);
    pSwap->swapIn = tmp;
    // swap out
    tmp = strtok(NULL,delims);
    pSwap->swapOut = tmp;
}

//
void Memory::GetMemoryFromCommand(MemorySwap *pSwap)
{
    int size = 1024;
    char result[size];
    const char *command = "vmstat";
    const char *fileName = "memory.out";

    ExecuteCommand(command, fileName, result, size, 3);

//    CommandPipe(command,result,size);
    GetSwap(result,pSwap);
}

void Memory::GetMemoryInfo(Memory *pMemory, QMultiMap<QString, QPair<QString, QString> > *pmultiMap)
{
    QPair<QString, QString> kv;
    QString cate = "Memory";

    GetMemoryFromFile(&(pMemory->sMemoryFile));

    kv.first = "memTotal";
    kv.second = pMemory->sMemoryFile.memTotal;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "memFree";
    kv.second = pMemory->sMemoryFile.memFree;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "memUsedRate";
    kv.second = pMemory->sMemoryFile.memUsedRate;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "buffers";
    kv.second = pMemory->sMemoryFile.buffers;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "cached";
    kv.second = pMemory->sMemoryFile.cached;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "swapCached";
    kv.second = pMemory->sMemoryFile.swapCached;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "active";
    kv.second = pMemory->sMemoryFile.active;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "inActive";
    kv.second = pMemory->sMemoryFile.inActive;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "swapTotal";
    kv.second = pMemory->sMemoryFile.swapTotal;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "swapFree";
    kv.second = pMemory->sMemoryFile.swapFree;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "swapUsedRate";
    kv.second = pMemory->sMemoryFile.swapUsedRate;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "dirty";
    kv.second = pMemory->sMemoryFile.dirty;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "slab";
    kv.second = pMemory->sMemoryFile.slab;
    pmultiMap->insert(cate, kv);

    GetMemoryFromCommand(&(pMemory->sMemorySwap));
    // 哆啦A梦的妹妹和跳跳虎还真是很登对
    kv.first = "swapIn";
    kv.second = pMemory->sMemorySwap.swapIn;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "swapOut";
    kv.second = pMemory->sMemorySwap.swapOut;
    pmultiMap->insert(cate, kv);
}
